﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.IO;
using System.Web;

namespace Twitter.Net
{
	public enum ResponseFormat
	{
		atom,
		json,
		rss,
		xml
	}


	/// <summary>
	/// Provides a C# interface to the Twitter API published at http://groups.google.com/group/twitter-development-talk/web/api-documentation
	/// </summary>
	public class TwitterProvider
	{
		private const string VERIFY_CREDENTIALS_URL = "http://twitter.com/account/verify_credentials.xml";

		#region Properties
		
		public string Username { get; set; }
		public string Password { protected get; set; }
		
		#endregion Properties

		#region Constructors
		
		public TwitterProvider()
		{

		}

		public TwitterProvider(string username, string password)
		{
			Username = username;
			Password = password;
		}

		#endregion Constructors

		#region Public Methods
		
		public bool CredentialsAreValid(out HttpStatusCode statusCode)
		{
			HttpWebRequest req = CreateGetRequest(VERIFY_CREDENTIALS_URL, Username, Password);
			string data = GetData(req, out statusCode);
			return (data == "<authorized>true</authorized>");
		}

		#endregion Public Methods

		#region Internal Methods

		internal HttpWebRequest CreateGetRequest(string url)
		{
			return CreateGetRequest(url, "", "");
		}

		internal HttpWebRequest CreateGetRequest(string url, string username, string password)
		{
			HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
			req.Method = "GET";

			if (!string.IsNullOrEmpty(username))
			{
				req.Credentials = new NetworkCredential(Username, Password);
			}

			return req;
		}

		internal HttpWebRequest CreatePostRequest(string url)
		{
			return CreatePostRequest(url, "", "");
		}

		internal HttpWebRequest CreatePostRequest(string url, string username, string password)
		{
			HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
			req.Method = "POST";

			if (!string.IsNullOrEmpty(username))
			{
				req.Credentials = new NetworkCredential(Username, Password);
			}

			return req;
		}

		internal string GetData(string url, out HttpStatusCode statusCode)
		{
			return GetData(url, "", "", out statusCode);
		}

		internal string GetData(string url, string username, string password, out HttpStatusCode statusCode)
		{
			HttpWebRequest req = CreateGetRequest(url, username, password);
			return GetData(req, out statusCode);
		}

		internal string GetData(HttpWebRequest req, out HttpStatusCode statusCode)
		{
			HttpWebResponse resp = null;

			try
			{
				//get the response
				resp = (HttpWebResponse)req.GetResponse();
				statusCode = resp.StatusCode;
				using (Stream receiveStream = resp.GetResponseStream())
				{
					Encoding encode = Encoding.GetEncoding("utf-8");
					using (StreamReader readStream = new StreamReader(receiveStream, encode))
					{
						return readStream.ReadToEnd();
					}
				}
			}
			finally
			{
				if (resp != null)
				{
					resp.Close();
				}
			}
		}

		internal string PostData(string url, Dictionary<string, string> postParams, out HttpStatusCode statusCode)
		{
			return PostData(url, postParams, "", "", out statusCode);
		}

		internal string PostData(string url, Dictionary<string, string> postParams, string username, string password, out HttpStatusCode statusCode)
		{
			HttpWebRequest req = CreatePostRequest(url, username, password);
			req.ContentType = "application/x-www-form-urlencoded";
			
			if (postParams != null && postParams.Count > 0)
			{
				//build the post param set
				string paramLine = string.Empty;
				foreach (KeyValuePair<string, string> kvp in postParams)
				{
					if (!string.IsNullOrEmpty(paramLine))
					{
						paramLine = string.Format("{0}&", paramLine);
					}

					paramLine = string.Format("{0}{1}={2}", paramLine, kvp.Key, HttpUtility.UrlEncode(kvp.Value));
				}

				//set the post values
				if (!string.IsNullOrEmpty(paramLine))
				{
					if (paramLine.EndsWith("&"))
					{
						paramLine.Remove(paramLine.Length - 1, 1);
					}
					byte[] buffer = System.Text.ASCIIEncoding.UTF8.GetBytes(paramLine);
					req.ContentLength = buffer.Length;
					using (Stream writer = req.GetRequestStream())
					{
						writer.Write(buffer, 0, buffer.Length);
					}
				}
			}

			return GetData(req, out statusCode);
		}

		#endregion Internal Methods
	}
}
